home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume7 / nlist < prev    next >
Encoding:
Text File  |  1989-08-05  |  50.7 KB  |  2,027 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Cetia, Toulon, France
  3. subject: v07i116: nlist -- display and monitor kernel variables and data structures
  4. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Reply-To: chris@cetia.UUCP (Chris Bertin)
  6.  
  7. Posting-number: Volume 7, Issue 116
  8. Submitted-by: chris@cetia.UUCP (Chris Bertin)
  9. Archive-name: nlist
  10.  
  11. [Amazing.  It looks like this should be easy to adapt to almost any flavor
  12. of Unix; it comes with SunOS 3.5, 4.3BSD, and System V R2 and R3 templates.
  13. Horray for portable programming!  ++bsa]
  14.  
  15. This is 'nlist'. There is a README file and manual that explain what it does,
  16. as well as a few examples of the things you can do with it. I tried posting
  17. it to comp.sources.unix, but nothing seems to be going on with that group any
  18. more (the last posting I received from comp.sources.unix is from the first
  19. of July...). I am not even getting replies to my mail to Rich Salz.
  20.  
  21. Anyway, if you have any questions, please email them to me.
  22.  
  23. Chris
  24.  
  25. ---------------------------------- cut here -------------------------------
  26. #! /bin/sh
  27. # This is a shell archive, meaning:
  28. # 1. Remove everything above the #! /bin/sh line.
  29. # 2. Save the resulting text in a file.
  30. # 3. Execute the file with /bin/sh (not csh) to create:
  31. #    README
  32. #    MANIFEST
  33. #    nlist.8
  34. #    nlist.c
  35. #    Makefile
  36. #    chars.sun
  37. #    config.sh
  38. #    dnlc.sun
  39. #    file.sun
  40. #    file.sys53
  41. #    minfo.sys5
  42. #    mount.sun
  43. #    mount.sys53
  44. #    syserr.sys5
  45. #    sysinfo1.sys5
  46. #    sysinfo2.sys5
  47. #    sysinfo3.sys5
  48. #    sysinfo4.sys5
  49. #    sysinfo5.sys5
  50. #    sar-s
  51. # This archive created: Wed Aug  2 17:52:40 1989
  52. export PATH; PATH=/bin:/usr/bin:$PATH
  53. if test -f 'README'
  54. then
  55.     echo shar: "will not over-write existing file 'README'"
  56. else
  57. cat << \SHAR_EOF > 'README'
  58.  
  59.                  -- N L I S T --
  60.  
  61. To make 'nlist', type 'sh config.sh'. I have built it on SYSV.2, SYSV.3,
  62. SunOs3.5, BSD4.3 and Mach, so I hope it will compile and run without
  63. problems on your system.
  64.  
  65. There are examples for Sun machines in *.sun and examples for System V
  66. machines in *.sys5*. BSD4.3 systems should be able to run some of the Sun
  67. scripts. If these scripts don't work on your machine, it means
  68. the structures are not quite identical to the ones I have here. It should
  69. be pretty easy to fix them, once you've read the manual. If symbols are not
  70. found, try adding or removing the leading symbol name underscore.
  71.  
  72. If you have any comments, you can Email them to me.
  73.  
  74. Chris Bertin    | -- CETIA -- 150, Av Marcelin Berthelot, Z.I. Toulon-Est
  75. +33(94)212005    | 83088 Toulon Cedex, France
  76.         | inria!cetia!chris
  77. SHAR_EOF
  78. fi
  79. if test -f 'MANIFEST'
  80. then
  81.     echo shar: "will not over-write existing file 'MANIFEST'"
  82. else
  83. cat << \SHAR_EOF > 'MANIFEST'
  84. README
  85. MANIFEST
  86. nlist.8
  87. nlist.c
  88. Makefile
  89. chars.sun
  90. config.sh
  91. dnlc.sun
  92. file.sun
  93. file.sys53
  94. minfo.sys5
  95. mount.sun
  96. mount.sys53
  97. syserr.sys5
  98. sysinfo1.sys5
  99. sysinfo2.sys5
  100. sysinfo3.sys5
  101. sysinfo4.sys5
  102. sysinfo5.sys5
  103. sar-s
  104. SHAR_EOF
  105. fi
  106. if test -f 'nlist.8'
  107. then
  108.     echo shar: "will not over-write existing file 'nlist.8'"
  109. else
  110. cat << \SHAR_EOF > 'nlist.8'
  111. .TH NLIST 8 LOCAL
  112. .SH NAME
  113. .ad b
  114. nlist \- display and monitor kernel variables and data structures
  115. .SH SYNOPSIS
  116. .B nlist
  117. [-aptux] [-f format] [-h header] [-l loops] [-m mem]
  118. .if n \{\
  119. .br
  120. .ti 2c\}
  121. [-n namelist] [-s sleep] [-D debug]  symbol|formula ...
  122. .SH DESCRIPTION
  123. .I Nlist
  124. reads kernel variables and displays them. It can be used to monitor variables
  125. or to display arrays of data structures or linked lists. It is also a full
  126. report generator, with a built-in calculator. It is very useful for kernel
  127. debugging (monitoring of debug variables, for example) and can even provide
  128. a user-configurable replacement for utilities like
  129. .I sar(1),
  130. on SYSV systems.
  131. See the EXAMPLE section below.
  132. .PP
  133. The toggle options are:
  134. .TP 12
  135. .I -a
  136. Auto increment the address by the size of the previous read. This is used
  137. to step through a structure with a minimum amount of address calculations.
  138. The auto-increment option is disabled if the cell contains any address
  139. calculation. See the SYMBOLS, FORMULAS and EXAMPLES sections.
  140. .TP
  141. .I -p
  142. Prepend the '0x' prefix, if the display type is in hexadecimal, or the '0'
  143. prefix if it is in octal. Essentially the '#' option of printf.
  144. .TP
  145. .I -t
  146. Print the time in the first column (ala 'sar').
  147. .TP
  148. .I -u
  149. Print unique lines only (excluding the time, if the -t flag is present).
  150. .TP
  151. .I -x
  152. Normally,
  153. .B nlist
  154. exits if a value doesn't fit in the print format, or if a symbol is not
  155. found in the name list. If this option is present,
  156. .B nlist
  157. will carry on silently. See the
  158. .B format
  159. option below. Also, if this flag is set and if a read failure occurs,
  160. the output will be a string of question marks (?).
  161. .PP
  162. The other options are:
  163. .TP 12
  164. .I -f format
  165. The argument is a simplified printf format: a number followed by a valid
  166. format type. See the FORMATS section below.
  167. .TP
  168. .I -h header
  169. If the argument is zero (0), no title will be printed. If it is one (1),
  170. a title is printed on the first line only. If it is any other value, the
  171. title will be reprinted every ${LINES} (24 by default).
  172. .TP
  173. .I -l loops
  174. Normally,
  175. .B nlist
  176. loops forever. The argument is the number of lines that will
  177. be displayed, excluding the headers.
  178. .TP
  179. .I -m memdev
  180. Read kernel memory from
  181. .B memdev
  182. instead of the default
  183. .B /dev/kmem.
  184. .TP
  185. .I -n namelist
  186. Read the namelist from
  187. .B namelist
  188. instead of
  189. .B /unix
  190. or
  191. .B /vmunix.
  192. .TP
  193. .I -s sleep
  194. The argument overrides the default one (1) second pause between line output.
  195. .TP
  196. .I -D debug
  197. This field is a level of debug. One (1) prints information about the read's,
  198. two (2) prints the control structure before it is analyzed, and
  199. three (3) prints it after it has been analyzed. See source code for details.
  200. .PP
  201. The arguments following these options are kernel symbols or formulas. They
  202. will be refered to as
  203. .I cells
  204. in this manual.
  205. .SH SYMBOLS
  206. A symbol is a valid name found in the kernel namelist. A read size may be
  207. supplied after the symbol name, following the special character
  208. .B '|'.
  209. If the print format is not a string (see FORMATS below), only sizes
  210. of 1, 2 and 4 may be given, meaning the symbol to be read is 1, 2 or 4 bytes
  211. big. The default is 4.
  212. .PP
  213. Symbols may be also followed by a positive or negative offset indicated by
  214. .I +value
  215. or
  216. .I -value.
  217. .PP
  218. They may also be followed by a positive or negative loop increment, following
  219. the special character
  220. .B '>':
  221. .I >value,
  222. or
  223. .I >+value,
  224. or
  225. .I >-value.
  226. .PP
  227. Loop incrementing is done for each line, after all the arguments have been
  228. evaluated. It differs from the 'auto-increment' option which will increment
  229. the address of each cell with the read size of the preceding one, before the
  230. read is done.
  231. .PP
  232. These values may be given in any order.
  233. .PP
  234. If a symbol name is followed by an exclamation mark ('!'), the read will
  235. be done once only and the cell won't be printed.
  236. .SH FORMULAS
  237. .B Nlist
  238. has a built-in stacking (reverse Polish) calculator. Arithmetic
  239. operations may be performed on any current value, preceding value or address
  240. of any field (cell). The first non-option argument is cell one (1).
  241. .PP
  242. The special characters are:
  243. .TP 6
  244. .I '#'
  245. means the current value of a cell. That value is the value read from memory
  246. or whatever may have been placed there by a
  247. calculation.
  248. .TP
  249. .I '^'
  250. means the value of a cell on the previous pass.
  251. .TP
  252. .I '&'
  253. means the address of a cell. The address is the memory location from which
  254. data is read.
  255. .PP
  256. The cell identification may be absolute or relative and the special
  257. character '.' means the current cell. For example, '&.' is the read-address
  258. for the current cell, '#1' is the current value of cell 1, '^+3' is
  259. the value of the third cell to the right, on the previous pass, and '#-2' is
  260. the current value of the second cell on the left.
  261. .PP
  262. The valid operations are: +, -, * or / for add, subtract, multiply or divide,
  263. respectively. The operands may be integers, current cell values, previous
  264. cell values or read-addresses.
  265. .PP
  266. Additionally, values or addresses may be initialized or recalculated on every
  267. pass, using the
  268. .B '!'
  269. and the
  270. .B '=',
  271. special symbols respectively. For example:
  272. .PP
  273. .ti 10
  274. .B "#. = &-1 #-2 +"
  275. .PP
  276. will set the current value to the sum of the read-address of the preceding
  277. cell and the current value of the second cell on the left.
  278. .PP
  279. .ti 10
  280. .B "^+1 ! 1"
  281. .PP
  282. will initialize the previous value of the cell on the right to one (1).
  283. Note that initialization cells are not printed.
  284. .PP
  285. If the
  286. .B -x
  287. flag is set, divisions by zero (0) return an error instead of causing
  288. .B nlist
  289. to exit.
  290. .PP
  291. Floating point exceptions, except divisions by zero caught by the
  292. calculator, are always fatal.
  293. .SH CONDITIONAL EVALUATION
  294. If a question mark ('?') is found it the argument, it indicates that
  295. the read address for the current cell has been calculated by another cell
  296. and that the read should take place only if the read-address is non-zero.
  297. Following cells will be skipped as well and the value displayed will be a
  298. string of dashes ('-'). Reading will resume on the next cell that contains
  299. a real symbol, or on the next line, which ever comes first.
  300. .SH FORMATS
  301. The global print format is set to hexadecimal, 8 characters wide, by default.
  302. It may be modified globally using the
  303. .I -h
  304. flag, or for each cell. The syntax of a format cell is: the special character
  305. .B '%',
  306. optionally followed by a positive value and followed by a identifier.
  307. .PP
  308. Formats supported are: %d, %u, %o, %x, %f (2 decimals), %s and %t. %t is
  309. time format, meaning the value is printed using ctime(3).
  310. .PP
  311. The optional value is the width of the cell. If an overflow occurs,
  312. .B nlist
  313. will exit, unless the
  314. .B -x
  315. flag is set, in which case a string of asterisks (*) will be displayed.
  316. .PP
  317. If the format is decimal and if the result of a calculation is not an integer,
  318. floating point format will be used automatically.
  319. .SH HEADERS
  320. Each cell may supply its own header, after the special character 
  321. .B ':'.
  322. If the header contains characters special to
  323. .B nlist,
  324. it must be quoted. If no header is supplied, the argument is printed.
  325. .SH EXAMPLES
  326. Here are now a few examples that will show most of the things
  327. that can be done with
  328. .B nlist:
  329. .PP
  330. Example 1
  331. .PP
  332. This command works on BSD and V7 systems that keep track of the
  333. total number of characters input and output, in '_tk_nin' and '_tk_nout',
  334. respectively.
  335. .PP
  336. .nf
  337.         nlist -t -f 9d -s 2                     \\
  338.                 _tk_nin                         \\
  339.                 _tk_nout                        \\
  340.                 '#. = #1 #2 +  : Total'         \\
  341.                 '#1 100 * #3 / : "% Input"'     \\
  342.                 '#2 100 * #3 / : "% Output"'
  343. .fi
  344. .PP
  345. Description, argument by argument:
  346. .PP
  347. The time will be printed at the start of each line (-t option), the print
  348. mode will be decimal, 9 characters wide, for all the cells (-f 9d),
  349. and the program will run continuously with a line of output
  350. every 2 seconds (-s 2).
  351. .PP
  352. The value of '_tk_nin' will be read into cell 1, the value of '_tk_nout' into
  353. cell 2, the sum of these 2 values will be placed in the current value
  354. of cell 3.
  355. .PP
  356. Cells 4 and 5 will print out the percentages of inputs and outputs
  357. respectively.
  358. .PP
  359. The result will be something like:
  360. .PP
  361. .TS
  362. rrrrrr.
  363. 16:18:39    _tk_nin    _tk_nout    Total    % Input    % Output
  364. 16:18:39    19160    994283    1013443    1.89    98.11
  365. 16:18:41    19160    994343    1013503    1.89    98.11
  366. 16:18:43    19160    994403    1013563    1.89    98.11
  367. 16:18:45    19160    994463    1013623    1.89    98.11
  368. .../...
  369. .TE
  370. .PP
  371. Example 2
  372. .PP
  373. This command works on a Sun 3, with a release 3.5EXPORT. If the
  374. mount structure hasn't changed on newer releases, it will work as well. It
  375. should also work on generic 4.3 BSD systems.
  376. .PP
  377. This example uses different print formats, different read sizes,
  378. loop increments and cell auto-increments.
  379. .PP
  380. .nf
  381.         nlist -pax -s 0 -f 8x -l 4            \\
  382.                 '^. 1 +       : " #"    %2d'  \\
  383.                 '_mounttab>28 : Vfsp'         \\
  384.                 '  |1         : Maj     %3o'  \\
  385.                 '  |1         : Min     %3o'  \\
  386.                 '             : Devvp'        \\
  387.                 '             : Bufp'         \\
  388.                 '             : Qinod'        \\
  389.                 '             : Qflags  |2'   \\
  390.                 '             : Btime   %5d'  \\
  391.                 '             : Ftime   %5d'
  392. .fi
  393. .PP
  394. Description, argument by argument:
  395. .PP
  396. Turn the 'prefix' option (-p), turn on the 'auto-increment' option (-a),
  397. continue if an overflow occurs (-x), don't pause between line displays (-s 0),
  398. use hexadecimal, 8 characters wide as a default print mode (-f 8x), and
  399. print out 4 lines (-l 4).
  400. .PP
  401. The next argument, on the next line, will just print a header by taking the
  402. value of the current cell on the previous pass (uninitialized, zero) and
  403. adding one (1) to it. Its header will be ' #' and its print format 2 decimal
  404. characters.
  405. .PP
  406. The next argument will cause the variable '_mounttab' to be read in and to
  407. be displayed with the 'Vfsp' title. When all the arguments will be processed,
  408. the address will be incremented by 28 (the size of the mount table
  409. structure). The read-address will be incremented by 4 for the next read,
  410. because auto-increment is turned on and because the read size is 4
  411. bytes (default).
  412. .PP
  413. The next 2 arguments will read 1 byte each (half a 'dev_t' type, on BSD),
  414. and display them as 'Maj' and 'Min', in octal, 3 characters wide.
  415. .PP
  416. The next 3 arguments are pointers, 4 bytes big. These cells are basically
  417. empty cells with a title (':').
  418. .PP
  419. The following argument is a short and the last 2 are longs, displayed in
  420. decimal, 6 characters wide.
  421. .PP
  422. The output will look something like this:
  423. .PP
  424. .if t \{\
  425. .TS
  426. rrrrrrrrrr.
  427. #    m_vfsp    maj    min    devvp    bufp    qinod    qflags    btime    ftime
  428. 1    0x110b50    03    0    0x110afc    0x10213c    0    0    0    0
  429. 2    0x104400    07    0    0x1044f4    0x10125c    0    0    0    0
  430. 3    0x104424    03    03    0x110fc8    0x102208    0    0    0    0
  431. 4    0x104594    03    07    0x1044cc    0x1013f4    0    0    0    0
  432. .TE\}
  433. .if n \{\
  434. .nf
  435.  
  436. #   m_vfsp maj min    devvp     bufp qinod qflags btime ftime
  437. 1 0x110b50  03   0 0x110afc 0x10213c     0      0     0     0
  438. 2 0x104400  07   0 0x1044f4 0x10125c     0      0     0     0
  439. 3 0x104424  03  03 0x110fc8 0x102208     0      0     0     0
  440. 4 0x104594  03  07 0x1044cc 0x1013f4     0      0     0     0
  441. .fi\}
  442. .PP
  443. Example 3
  444. .PP
  445. This command will dump the 'dnlc' cache on a Sun. It uses the string output
  446. format and the addressing feature needed to follow linked lists. It should
  447. work without too many modifications on generic 4.3 systems.
  448. .PP
  449. .nf
  450.         nlist -ax -h1 -s 0 -f6x -l 10         \\
  451.                 '_ncache        : Hshnxt'     \\
  452.                 '               : Hshprv'     \\
  453.                 '               : Lrunxt'     \\
  454.                 '               : Lruprv'     \\
  455.                 '               : Vp'         \\
  456.                 '               : Dp'         \\
  457.                 '|1             : Len  %3d'   \\
  458.                 '|15            : Name %15s'  \\        <== 8
  459.                 '               : Ucred'      \\
  460.                 '@&1 = #1'                             <== 10
  461. .fi
  462. .PP
  463. Description of arguments not yet explained.
  464. .PP
  465. The argument on the 8th line displays a string of
  466. characters, 15 bytes long.
  467. .PP
  468. The last (10th) argument shows how one can follow a linked list. The '@'
  469. means that the cell won't be printed, '&1 = #1' sets
  470. the address of the first cell to the value of the first cell.
  471. .PP
  472. Here is the result:
  473. .PP
  474. .if t \{\
  475. .TS
  476. rrrrrrrrr
  477. rrrrrrrlr.
  478. Hshnxt    Hshprv    Lrunxt    Lruprv    Vp    Dp    Len    Name    Ucred
  479. a02e0    0    a051c    a0e38    a1db0    a1ac4    0    ......\\.......\\    a1518
  480. a1360    a051c    a1728    a0fc4    92b6c    9242e    3    usrxcvsub.c0or0    0
  481. a1ddc    a02e0    a1964    a190c    92834    90668    11    usr.MC68010nd.o    0
  482. a16d0    a1360    a138c    a0de0    95070    92b6c    5    spool.heds40.os    0
  483. a17d8    a1ddc    a117c    a1200    96962    92766    3    ucbf.hub.cld.av    0
  484. a0a9c    a16d0    a0860    a0390    93c52    97be4    7    nlist.oa1.c.old    0
  485. a10cc    a17d8    a030c    a1d00    95a18    92dd6    2    ldrace.h.c30rc1    0
  486. a0cd8    a0a9c    a1bcc    a093c    92c3a    95476    6    time.hh0p@svc.2    0
  487. .../...
  488. .TE\}
  489. .if n \{\
  490. .nf
  491. Hshnxt Hshprv Lrunxt Lruprv    Vp    Dp Len            Name Ucred
  492.  a02e0      0  a051c  a0e38 a1db0 a1ac4   0 ......\\.......\\ a1518
  493.  a1360  a051c  a1728  a0fc4 92b6c 9242e   3 usrxcvsub.c0or0     0
  494.  a1ddc  a02e0  a1964  a190c 92834 90668  11 usr.MC68010nd.o     0
  495.  a16d0  a1360  a138c  a0de0 95070 92b6c   5 spool.heds40.os     0
  496.  a17d8  a1ddc  a117c  a1200 96962 92766   3 ucbf.hub.cld.av     0
  497.  a0a9c  a16d0  a0860  a0390 93c52 97be4   7 nlist.oa1.c.old     0
  498.  a10cc  a17d8  a030c  a1d00 95a18 92dd6   2 ldrace.h.c30rc1     0
  499.  a0cd8  a0a9c  a1bcc  a093c 92c3a 95476   6 time.hh0p@svc.2     0
  500.  .../...
  501. .fi\}
  502. .PP
  503. Example 4
  504. .PP
  505. The next command will show you how to use indirection. On BSD systems, the
  506. variable '_file' is not the beginning of the file table, but a pointer to
  507. the table. It will also show you how to follow a pointer inside a structure,
  508. in this case, the 'ucred' pointer.
  509. .PP
  510. .nf
  511.         nlist -a -s 0 -f7x -h 1 -l 10           \\
  512.                 '^. 1 +         : "  #"    %3d' \\
  513.                 '_file!'                        \\     <== 3
  514.                 '&+1 ! #-1'                     \\     <== 4
  515.                 '>26            : flag     %4o' \\     <== 5
  516.                 '|2             : type     %4x' \\
  517.                 '|2             : count    %6d' \\
  518.                 '|2             : msgcount %6d' \\
  519.                 '               : fops'         \\
  520.                 '               : fdata'        \\
  521.                 '               : offset   %6x' \\
  522.                 '               : cred'         \\
  523.                 '&. = #-1 |2    : Crref    %5d' \\     <== 13
  524.                 '|2             : Uid      %4d' \\
  525.                 '|2             : Gid      %4d'
  526. .fi
  527. .PP
  528. Description of arguments not yet explained:
  529. .PP
  530. Line 3: The variable '_file' is read but the cell is not displayed because
  531. of the trailing '!'.
  532. .PP
  533. Line 4: Set the read-address of the cell on the right to the value read in the
  534. preceding cell.
  535. .PP
  536. Line 5: This cell's read-address has been initialized by the preceding cell.
  537. On the next pass, it will be incremented by 26 bytes (the size of the file
  538. structure).
  539. .PP
  540. Line 13: Here, we follow the the 'ucred' pointer and display the first
  541. element from that structure. The next 2 cell will auto-increment from
  542. that new address.
  543. .PP
  544. Here is the file table:
  545. .PP
  546. .if t \{\
  547. .TS
  548. rrrrrrrrrrrr.
  549. #    flag    type    count    msgcou    fops    fdata    offset    cred    Crref    Uid    Gid
  550. 1    1    1    0    0    7a0f8    970a0    9e2    1047d0    5    110    100
  551. 2    1    1    0    0    7a0f8    93ebc    29b    1047d0    5    110    100
  552. 3    1    1    0    0    7a0f8    2183ac    1047d6    1047d0    5    110    100
  553. 4    1    1    0    0    7a0f8    94c6a    80a7c    1047d0    5    110    100
  554. 5    1    1    0    0    7a0f8    94c6a    8a6a4    1047d0    5    110    100
  555. 6    3    2    0    0    799fc    0    0    110b24    97    0    0
  556. 7    2    1    0    0    7a0f8    93ebc    29b    1047d0    5    110    100
  557. .../...
  558. .TE\}
  559. .if n \{\
  560. .nf
  561. # flag type count msgcou    fops   fdata offset    cred Crref Uid Gid
  562. 1    1    1     0      0   7a0f8   970a0    9e2  1047d0     5 110 100
  563. 2    1    1     0      0   7a0f8   93ebc    29b  1047d0     5 110 100
  564. 3    1    1     0      0   7a0f8  2183ac 1047d6  1047d0     5 110 100
  565. 4    1    1     0      0   7a0f8   94c6a  80a7c  1047d0     5 110 100
  566. 5    1    1     0      0   7a0f8   94c6a  8a6a4  1047d0     5 110 100
  567. 6    3    2     0      0   799fc       0      0  110b24    97   0   0
  568. 7    2    1     0      0   7a0f8   93ebc    29b  1047d0     5 110 100
  569. .../...
  570. .fi\}
  571. .PP
  572. Example 5:
  573. .PP
  574. Dump the mount table on a SYSV.3 88K Motorola system ('dev_t' is a long on
  575. that system):
  576. .PP
  577. .nf
  578.         nlist -ap -s 0 -f8x -l 4                \\
  579.                 '^. 1 +: #%2d'                  \\
  580.                 '_mount |2 >36  : Flags  %6o'   \\
  581.                 '|2             : Type   %4d'   \\
  582.                 '               : Bsize  %5o'   \\
  583.                 '               : Dev    %6o'   \\
  584.                 '               : Bufp'         \\
  585.                 '               : Inop'         \\
  586.                 '               : Mountp'       \\
  587.                 '|2             : Rflags'       \\
  588.                 '               : Namep'        \\
  589.                 '               : Bcount %6d'
  590. .fi
  591. .PP
  592. Example 6:
  593. .PP
  594. This will do what 'sar -s' does, on SYSV:
  595. .PP
  596. .nf
  597.         echo "`uname -a`    `date +%D`\\n"
  598.  
  599.         nlist -xat -f7d -s 1 -h1                \\
  600.                 '@sysinfo'                      \\
  601.                 '@'                             \\
  602.                 '@'                             \\
  603.                 '@'                             \\
  604.                 '@#. = #1 ^1 -'                 \\
  605.                 '@#. = #2 ^2 -'                 \\
  606.                 '@#. = #3 ^3 -'                 \\
  607.                 '@#. = #4 ^4 -'                 \\
  608.                 '@#-1 #-2 #-3 #-4 +++'          \\
  609.                 '#6 100 * #-1 /: "%usr"'        \\
  610.                 '#7 100 * #-2 /: "%sys"'        \\
  611.                 '#8 100 * #-3 /: "%wio"'        \\
  612.                 '#5 100 * #-4 /: "%idle"'
  613. .fi
  614. .PP
  615. Finally, an example of the neat things you can do with
  616. .B nlist:
  617. .PP
  618. .nf
  619.         nlist -h 1 -f 12u -l 31 -s 0 '^+1 ! 1' '^2 2 *:"Powers of 2"'
  620. .fi
  621. .SH FILES
  622. /unix or /vmunix       name list
  623. .br
  624. /dev/kmem              kernel memory
  625. .SH BUGS
  626. Conditional evaluation is very basic.
  627. .PP
  628. The syntax is not exactly user-friendly.
  629. .SH AUTHOR
  630. Chris Bertin.
  631. SHAR_EOF
  632. fi
  633. if test -f 'nlist.c'
  634. then
  635.     echo shar: "will not over-write existing file 'nlist.c'"
  636. else
  637. cat << \SHAR_EOF > 'nlist.c'
  638. #ifndef lint
  639. static char ID[] = "@(#)nlist.c    2.1 Copyright (C) 1989 Chris Bertin 89/07/31";
  640. #endif
  641. /*
  642.  * nlist -- display and monitor kernel variables. Dump kernel structures.
  643.  *
  644.  *    This program is free for redistribution as long as this header
  645.  *    remains unchanged.
  646.  *
  647.  *                Copyleft Chris Bertin, July 1989
  648.  *
  649.  */
  650. #include    <stdio.h>
  651. #ifdef    V7
  652. #include    <a.out.h>
  653. #else
  654. #include    <nlist.h>
  655. #endif    /* V7 */
  656. #ifdef    SYSV
  657. #include    <string.h>
  658. #else
  659. #include    <strings.h>
  660. #endif    /* SYSV */
  661. #include    <ctype.h>
  662. #include    <memory.h>
  663. #include    <time.h>
  664. #include    <sys/types.h>
  665. #include    <sys/signal.h>
  666. #ifdef    SYSV
  667. #include    <sys/var.h>
  668. #endif
  669.  
  670. #define NLISTBUG    /* see comment in fixnlist() */
  671.  
  672. #ifndef    SYSV
  673. #define DEF_NLIST    "/vmunix"    /* default namelist */
  674. #else
  675. #define DEF_NLIST    "/unix"
  676. #endif
  677. #define DEF_KMEM    "/dev/kmem"    /* default memory device */
  678. #define DEF_SLEEP    1        /* default pause between displays */
  679. #define DEF_WIDTH    8        /* default print width */
  680. #define DEF_LOOPS    -1        /* default number of loops (infinite) */
  681. #define DEF_RDSIZE    4        /* default read size */
  682.  
  683. /* misc return values */
  684. #define R_OK        0        /* OK */
  685. #define R_NOPRINT    1        /* value was computed but don't print */
  686. #define R_FLOAT        2        /* print value in float format */
  687. #define R_SKIP        3        /* skip this entry */
  688. #define R_ERR        -1        /* print error value */
  689.  
  690. /* misc */
  691. #define CDEPTH        4        /* max number of push for formulas */
  692. #define NDEC        2        /* number of decimals for float */
  693. #define NSPACES        1        /* number of spaces between fields */
  694.  
  695. /* header special characters */
  696. #define H_NOPRINT    '@'        /* don't print if first character */
  697. #define H_POST        ':'        /* real header start character */
  698. #define H_SET        '='        /* set field to value */
  699. #define H_INIT        '!'        /* initialize field to value */
  700. #define H_SIZE        '|'        /* read size (real symbols only) */
  701. #define H_FMT        '%'        /* field print width */
  702. #define H_INCR        '>'        /* increment address on next loop */
  703. #define H_NONZERO    '?'        /* quit if this address is 0 */
  704.  
  705. /* field identifiers in formulas. (For example: #1: value of field1, */
  706. /* ^+1: previous value of next field, &.: nlist address in current field) */
  707. #define H_CURVAL    '#'        /* current value in field number */
  708. #define H_PREVAL    '^'        /* previous value in field number */
  709. #define H_ADDR        '&'        /* the nlist address of the field */
  710. #define H_CURFIELD    '.'        /* current field */
  711.  
  712. /* values for -h flag */
  713. #define HD_NONE        0        /* don't print header */
  714. #define HD_ONCE        1        /* print header once only */
  715. #define HD_PAGE        2        /* print header every $LINES lines */
  716.  
  717. typedef float    val_t;
  718. typedef    struct nlist    nl_t;
  719.  
  720. typedef    struct field {
  721.     nl_t    *f_nl;            /* nlist entry pointer */
  722.     char    *f_arg;            /* original argument */
  723.     char    *f_form;        /* formula or symbol */
  724.     char    *f_post;        /* title */
  725.     char    *f_fmt;            /* print format (dec, oct, hex...) */
  726.     char    *f_buf;            /* read buffer for string printf's */
  727.     short     f_flags;        /* features */
  728.     short     f_width;        /* print width */
  729.     short     f_rdsize;        /* read size */
  730.     off_t     f_offset;        /* address offset */
  731.     off_t     f_incr;        /* address increment */
  732.     val_t     f_curval;        /* current value */
  733.     val_t     f_preval;        /* previous value */
  734. } fld_t;
  735.  
  736. /* f_flags bits */
  737. #define F_TITLE        0x1        /* Title is present */
  738. #define F_SYM        0x2        /* valid symbol */
  739. #define F_SET        0x4        /* set value */
  740. #define F_INIT        0x8        /* set value once only */
  741. #define F_DONE        0x10        /* init done */
  742. #define F_QUOTED    0x20        /* header is quoted. Don't clean it */
  743. #define F_NONZERO    0x40        /* quit if address is 0 */
  744. #define F_TIME        0x80        /* print the value as date/time */
  745. #define F_READOK    0x100        /* OK to read size other that 1,2,4 */
  746.  
  747. extern    char *optarg, *getenv(), *parsearg(), *alloc(), *calloc();
  748. extern    char *prfmt(), *spaces(), *cleanbuf();
  749. extern    char *sys_errlist[];
  750. extern    int errno, optind;
  751. extern    double ceil();
  752.  
  753. /* formats */
  754. char    decfmt[] =    "%*d";        /* decimal print mode */
  755. char    unsfmt[] =    "%*u";        /* unsigned decimal print mode */
  756. char    octfmt[] =    "%*o";        /* octal print mode */
  757. char    hexfmt[] =    "%*x";        /* hex print mode */
  758. char    flofmt[] =    "%*.*f";    /* floating point format */
  759. char    strfmt[] =    "%*.*s";    /* string print format */
  760. #ifndef    V7
  761. char    extoctfmt[] =    "%#*o";        /* hex with '0' prefix */
  762. char    exthexfmt[] =    "%#*x";        /* octal with '0x' prefix */
  763. #endif
  764. #define    DEF_FMT        hexfmt        /* default print format */
  765.  
  766. val_t    calc[CDEPTH];            /* calculator stack */
  767. int    cdepth;                /* calculator stack depth */
  768.  
  769. int    tim, uniq, fmtprefix, debug, autoincr;    /* flags with default 0 */
  770. int    strict = 1;            /* flags with default 1 */
  771. char    *buf, *hdr;            /* line and header buffers */
  772. char    *pname;                /* argv[0], for error messages */
  773.  
  774. char    *kmemf    = DEF_KMEM;
  775. char    *nlistf    = DEF_NLIST;
  776. char     *fmt    = DEF_FMT;
  777. int    slp    = DEF_SLEEP;
  778. int    width    = DEF_WIDTH;
  779. int    nloops    = DEF_LOOPS;
  780. int    header    = HD_PAGE;
  781.  
  782. main (argc, argv)
  783.     char        **argv;
  784. {
  785.     register int    mem, i;
  786.     int        nsymbols, maxw, prtime;
  787.     register fld_t    *baseflp, *flp;
  788.     nl_t        *nl;
  789.     char        *p;
  790.     int        onfpe();
  791.  
  792.     pname = *argv;
  793.     while ((i = getopt(argc, argv, "aD:f:h:l:m:n:ps:tux")) != -1) {
  794.         switch (i) {
  795.         case 'a':
  796.             autoincr++;
  797.             break;
  798.         case 'D':
  799.             debug = stoi(&optarg, "debug level", 0, 0);;
  800.             break;
  801.         case 'f':
  802.             fmt = prfmt(&optarg, &width, &prtime, 0, optarg);
  803.             break;
  804.         case 'h':
  805.             header = stoi(&optarg, "header value", 1, 0);
  806.             break;
  807.         case 'l':
  808.             nloops = stoi(&optarg, "number of loops", 0, 0);
  809.             break;
  810.         case 'm':
  811.             kmemf = optarg;
  812.             break;
  813.         case 'n':
  814.             nlistf = optarg;
  815.             break;
  816.         case 'p':
  817.             fmtprefix++;
  818.             break;
  819.         case 's':
  820.             slp = stoi(&optarg, "sleep time", 0, 0);
  821.             break;
  822.         case 't':
  823.             tim++;
  824.             break;
  825.         case 'u':
  826.             uniq++;
  827.             break;
  828.         case 'x':
  829.             strict = 0;
  830.             break;
  831.         default:
  832.             usage();
  833.         }
  834.     }
  835.     argc -= optind;
  836.     argv += optind;
  837.     if (argc <= 0)
  838.         usage();
  839.     if ((mem = open (kmemf, 0)) < 0)
  840.         perrexit (kmemf);
  841.     baseflp = (fld_t *) alloc((int) (argc * sizeof (fld_t)));
  842.     nl = (nl_t *) alloc((int) ((argc + 2) * sizeof (nl_t)));
  843.     for (flp = baseflp, maxw = nsymbols = 0, i = 0; i < argc; i++, flp++) {
  844.         p = parsearg(flp, *(argv + i));
  845.         if (flp->f_fmt != NULL)
  846.             maxw += flp->f_width + NSPACES;
  847.         if (flp->f_flags & F_SYM) {
  848.             flp->f_nl = nl + nsymbols;
  849.             nsymbols++;
  850. #ifdef    V7
  851.             (void) strncpy(flp->f_nl->n_name, p, SYMLENGTH);
  852. #else
  853.             flp->f_nl->n_name = p;
  854. #endif
  855.             continue;
  856.         }
  857.         if (autoincr && i > 0 && flp->f_incr == 0 && *p == '\0') {
  858.             sprintf(p = alloc(32), "%c%c%c%c-1 %d +", H_ADDR,
  859.                 H_CURFIELD, H_SET, H_ADDR, (flp - 1)->f_rdsize);
  860.             flp->f_flags |= F_SET;
  861.         }
  862.         flp->f_nl = nl + (argc - i + nsymbols + 1);
  863.         flp->f_form = p;
  864.     }
  865.     if (maxw == 0) {
  866.         fprintf(stderr, "%s: nothing to print\n", pname);
  867.         exit (1);
  868.     }
  869.     if (nsymbols) {
  870.         donlist(nl, mem, nsymbols);
  871.         for (i = 0, flp = baseflp; i < argc; i++, flp++)
  872.             if (flp->f_offset && flp->f_nl->n_value)
  873.                 flp->f_nl->n_value += flp->f_offset;
  874.     }
  875.     if (header != HD_NONE) {
  876.         hdr = alloc(maxw);
  877.         for (p = hdr, i = 0, flp = baseflp; i < argc; i++, flp++) {
  878.             if (flp->f_fmt == NULL)
  879.                 continue;
  880.             sprintf(p, "%s%*.*s", spaces(NSPACES), flp->f_width,
  881.                 flp->f_width, flp->f_post? flp->f_post: flp->f_arg);
  882.             p += flp->f_width + NSPACES;
  883.         }
  884.     }
  885.     (void) signal(SIGFPE, onfpe);
  886.     for (;;) {
  887.         if (process(baseflp, argc, mem, maxw, prtime)) {
  888.             outputline();
  889.             if (--nloops == 0)
  890.                 break;
  891.         }
  892.         (void) sleep((unsigned) slp);
  893.     }
  894.     return (0);
  895. }
  896.  
  897. /*
  898.  * Process the arguments once. Return 1 if 'buf' is to be printed.
  899.  */
  900. process(baseflp, max, mem, maxw, prtime)
  901.     register fld_t    *baseflp;
  902.     register int    max, mem, maxw;
  903. {
  904.     register int    i;
  905.     register char    *p;
  906.     register fld_t    *flp;
  907.     static char    *lastbuf, *tmp;
  908.  
  909.     if (buf == NULL) {
  910.         buf = alloc(maxw);
  911.         lastbuf = alloc(maxw);
  912.         tmp = alloc(BUFSIZ);
  913.     }
  914.     for (flp = baseflp, buf[0] = '\0', i = 0; i < max; i++, flp++) {
  915.         tmp[0] = '\0';
  916.         switch (analyze(baseflp, flp, max, mem)) {
  917.         case R_NOPRINT:
  918.             continue;
  919.         case R_SKIP:
  920.             sprintf(tmp, strfmt, flp->f_width, flp->f_width,
  921.                 "--------------------");
  922.             break;
  923.         case R_FLOAT:
  924.             sprintf(tmp, flofmt, flp->f_width, NDEC, flp->f_curval);
  925.             break;
  926.         case R_OK:
  927.             p = flp->f_fmt;
  928.             if (p == strfmt) {
  929.                 if (prtime || (flp->f_flags & F_TIME)) {
  930.                     time_t t = (time_t) flp->f_curval;
  931.                     (void) strncpy(flp->f_buf, ctime(&t),
  932.                         flp->f_width);
  933.                 }
  934.                 sprintf(tmp, strfmt, flp->f_width, flp->f_width,
  935.                     cleanbuf(flp->f_buf, flp->f_width));
  936.                 break;
  937.             }
  938. #ifndef    V7
  939.             if (fmtprefix && (long) flp->f_curval) {
  940.                 if (flp->f_fmt == hexfmt)
  941.                     p = exthexfmt;
  942.                 else if (flp->f_fmt == octfmt)
  943.                     p = extoctfmt;
  944.             }
  945. #endif
  946.             sprintf(tmp, p, flp->f_width, (long) flp->f_curval);
  947.             break;
  948.         case R_ERR:
  949.             if (strict) {
  950.                 outputline();
  951.                 fprintf(stderr, "%s: symbol '%s' not found\n",
  952.                     pname, flp->f_nl->n_name);
  953.                 exit (1);
  954.             }
  955.             sprintf(tmp, strfmt, flp->f_width, flp->f_width,
  956.                 "????????????????????");
  957.             break;
  958.         }
  959.         if (strlen(tmp) > flp->f_width) {
  960.             if (strict) {
  961.                 outputline();
  962.                 fprintf(stderr, "%s: print overflow\n", pname);
  963.                 exit (1);
  964.             }
  965.             sprintf(tmp, strfmt, flp->f_width, flp->f_width,
  966.                 "********************");
  967.         }
  968.         (void) strcat(buf, spaces(NSPACES));
  969.         (void) strcat(buf, tmp);
  970.     }
  971.     for (i = 0, flp = baseflp; i < max; i++, flp++) {
  972.         flp->f_preval = flp->f_curval;
  973.         if (flp->f_incr && flp->f_nl->n_value)
  974.             flp->f_nl->n_value += flp->f_incr;
  975.     }
  976.     if (uniq) {
  977.         if (strcmp(buf, lastbuf) == NULL)
  978.             return (0);
  979.         (void) strcpy(lastbuf, buf);
  980.     }
  981.     return(1);
  982. }
  983.  
  984. /*
  985.  * Print output buffer, adding title if needed. Exit if err is set.
  986.  */
  987. outputline()
  988. {
  989.     static int    lines, nlines;
  990.     char        *p;
  991.  
  992.     if (buf == NULL || *buf == '\0')
  993.         return;
  994.     if (header != HD_NONE) {
  995.         if (nlines == 0)
  996.             lines = nlines = (p = getenv("LINES"))? atoi(p): 24;
  997.         if (lines == nlines) {
  998.             printline(hdr);
  999.             lines = 2;
  1000.         }
  1001.         lines++;
  1002.         if (header == HD_ONCE)
  1003.             header = HD_NONE;
  1004.     }
  1005.     printline(buf);
  1006. }
  1007.  
  1008. /*
  1009.  * Print a line, with the current time if -t flag present.
  1010.  */
  1011. printline(line)
  1012.     char            *line;
  1013. {
  1014.     time_t            t;
  1015.     register struct tm    *tm;
  1016.  
  1017.     if (tim) {
  1018.         (void) time(&t);
  1019.         tm = localtime(&t);
  1020.         printf("%2d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
  1021.     }
  1022.     printf("%s\n", line);
  1023.     fflush(stdout);
  1024. }
  1025.  
  1026. /*
  1027.  * Parse an argument and initialize the control structure. Return a pointer
  1028.  * to a symbol without any trailers, if the argument is a symbol name.
  1029.  */
  1030. char *
  1031. parsearg(flp, str)
  1032.     register fld_t    *flp;
  1033.     char        *str;
  1034. {
  1035.     char        *p;
  1036.     register char    *pp, *xp;
  1037.     register char    c;
  1038.     int        endsym, w, prtime;
  1039.  
  1040.     flp->f_rdsize = DEF_RDSIZE;
  1041.     flp->f_width = width;
  1042.     flp->f_fmt = fmt;
  1043.     (void) skipspaces(&str);
  1044.     if (*str == H_NOPRINT) {
  1045.         flp->f_fmt = NULL;
  1046.         str++;
  1047.         (void) skipspaces(&str);
  1048.     }
  1049.     if (isalpha(*str) || *str == '_')
  1050.         flp->f_flags |= F_SYM;
  1051.     flp->f_arg = str;
  1052.     (void) strcpy(pp = alloc(strlen(str) + 1), str);
  1053.     for (endsym = 0, p = pp; *p; ) {
  1054.         (void) skipspaces(&p);
  1055.         xp = p;
  1056.         switch (*p++) {
  1057.         case H_POST:
  1058.             endsym++;
  1059.             (void) skipspaces(&p);
  1060.             if ((c = *p) != '\'' && c != '"') {
  1061.                 flp->f_post = p;
  1062.                 break;
  1063.             }
  1064.             flp->f_post = ++p;
  1065.             flp->f_flags |= F_QUOTED;
  1066.             while (*p != c)
  1067.                 if (*p++ == '\0') {
  1068.                     fprintf(stderr,
  1069.                     "%s: missing quote in header -- %s\n",
  1070.                         pname, pp);
  1071.                     exit (1);
  1072.                 }
  1073.             *p++ = '\0';
  1074.             break;
  1075.         case H_FMT:
  1076.             endsym++;
  1077.             flp->f_fmt = prfmt(&p, &w, &prtime, 1, flp->f_arg);
  1078.             if (w)
  1079.                 flp->f_width = w;
  1080.             if (flp->f_fmt == strfmt) {
  1081.                 flp->f_buf = alloc(flp->f_width + 1);
  1082.                 if (prtime)
  1083.                     flp->f_flags |= F_TIME;
  1084.                 else
  1085.                     flp->f_flags |= F_READOK;
  1086.             }
  1087.             break;
  1088.         case H_SIZE:
  1089.             endsym++;
  1090.             flp->f_rdsize = stoi(&p, "read size", 0, 1);
  1091.             break;
  1092.         case H_INCR:
  1093.             endsym++;
  1094.             flp->f_incr = stoi(&p, "increment value", 1, 1);
  1095.             break;
  1096.         case H_SET:
  1097.             flp->f_flags |= F_SET;
  1098.             break;
  1099.         case H_INIT:
  1100.             *(p - 1) = (flp->f_flags & F_SYM)? '\0': H_SET;
  1101.             flp->f_flags |= (F_SET|F_INIT);
  1102.             flp->f_fmt = NULL;
  1103.             break;
  1104.         case '+':
  1105.         case '-':
  1106.             if (flp->f_flags & F_SYM)
  1107.                 endsym++;
  1108.             --p;
  1109.             flp->f_offset = (val_t) stoi(&p, "offset", 1, 1);
  1110.             break;
  1111.         case H_NONZERO:
  1112.             endsym++;
  1113.             flp->f_flags |= F_NONZERO;
  1114.             break;
  1115.         default:
  1116.             continue;
  1117.         }
  1118.         if (! endsym)
  1119.             continue;
  1120.         *xp = '\0';
  1121.     }
  1122.     if (flp->f_buf == NULL)
  1123.         flp->f_buf = alloc(flp->f_rdsize);
  1124.     if ((flp->f_flags & F_QUOTED) == 0)
  1125.         cleanspaces(flp->f_post);
  1126.     cleanspaces(pp);
  1127.     cleanspaces(flp->f_arg);
  1128.     return (pp);
  1129. }
  1130.  
  1131. /*
  1132.  * Handle symbols, formulas, reads, calculator, etc...
  1133.  */
  1134. analyze(baseflp, flp, max, mem)
  1135.     register fld_t    *baseflp, *flp;
  1136.     register int    max, mem;
  1137. {
  1138.     fld_t        *nfp;
  1139.     char        *p, *form, *fmtp;
  1140.     register int    i;
  1141.     register val_t    *vp;
  1142.     int        prev, addr, seta;
  1143.     static int    skiptonext;
  1144.  
  1145.     if (flp == baseflp)
  1146.         skiptonext = 0;
  1147.     if (debug > 1)
  1148.         showfl(flp, flp - baseflp, "start analyze");
  1149.     if (flp->f_flags & F_DONE)
  1150.         return (R_NOPRINT);
  1151.     if (flp->f_flags & F_INIT)
  1152.         flp->f_flags |= F_DONE;
  1153.     prev = addr = seta = 0;
  1154.     fmtp = flp->f_fmt;
  1155.     p = form = flp->f_form;
  1156.     if (flp->f_flags & F_SYM) {
  1157.         skiptonext = 0;
  1158.         if (flp->f_nl->n_value == 0)
  1159.             return (R_ERR);
  1160.         flp->f_curval = (val_t) doread(flp->f_nl->n_name, kmemf, mem,
  1161.             flp->f_nl->n_value, flp->f_buf, flp->f_rdsize,
  1162.             (flp->f_flags & F_READOK));
  1163.         return ((fmtp == flofmt)? R_FLOAT: (fmtp? R_OK: R_NOPRINT));
  1164.     }
  1165.     for (i = 0; i < CDEPTH; i++)
  1166.         calc[i] = 0;
  1167.     cdepth = 0;
  1168.     vp = &flp->f_curval;
  1169.     if (flp->f_flags & F_SET) {
  1170.         nfp = baseflp + fn(baseflp, flp, &p, &prev, &seta, max, 0) - 1;
  1171.         if (seta == 0) {
  1172.             flp = nfp;
  1173.             vp = prev? &flp->f_preval: &flp->f_curval;
  1174.         }
  1175.         (void) skipspaces(&p);
  1176.         if (*p++ != H_SET)
  1177.             badf(form, --p, "invalid 'set' format");
  1178.     }
  1179.     *vp = 0;
  1180.     while (*p) {
  1181.         if (skipspaces(&p))
  1182.             continue;
  1183.         if (i = isdigit(*p))
  1184.             *vp = stoi(&p, "formula", 1, 1);
  1185.         else if (i = fn(baseflp, flp, &p, &prev, &addr, max, 1)) {
  1186.             if (addr)
  1187.                 *vp =  (val_t) (baseflp + i - 1)->f_nl->n_value;
  1188.             else
  1189.                 *vp = (prev? (baseflp + i - 1)->f_preval:
  1190.                          (baseflp + i - 1)->f_curval);
  1191.         }
  1192.         if (i) {
  1193.             if (push(*vp) == R_ERR)
  1194.                 badf(form, p, "stack overflow");
  1195.             *vp = 0;
  1196.             continue;
  1197.         }
  1198.         switch (*p++) {
  1199.         case '+':
  1200.             calc[1] = calc[1] + calc[0];
  1201.             break;
  1202.         case '-':
  1203.             calc[1] = calc[1] - calc[0];
  1204.             break;
  1205.         case '*':
  1206.             calc[1] = calc[1] * calc[0];
  1207.             break;
  1208.         case '/':
  1209.             if (calc[0] != 0)
  1210.                 calc[1] = calc[1] / calc[0];
  1211.             else if (strict)
  1212.                 badf(form, --p, "zero divide");
  1213.             else
  1214.                 return (R_ERR);
  1215.             break;
  1216.         default:
  1217.             badf(form, --p, "invalid operand");
  1218.         }
  1219.         *vp = 0;
  1220.         if (pop() == R_ERR)
  1221.             badf(form, --p, "stack empty");
  1222.     }
  1223.     if (*vp == 0)
  1224.         *vp = calc[0];
  1225.     if (seta)
  1226.         nfp->f_nl->n_value = (long) *vp;
  1227.     if (debug > 2)
  1228.         showfl(flp, flp - baseflp, "end analyze");
  1229.     if ((flp->f_flags & F_NONZERO) && flp->f_nl->n_value == 0)
  1230.         skiptonext++;
  1231.     if (skiptonext)
  1232.         return (fmtp? R_SKIP: R_NOPRINT);
  1233.     if (flp->f_nl->n_value)
  1234.         flp->f_curval = (val_t) doread(flp->f_nl->n_name, kmemf, mem,
  1235.             flp->f_nl->n_value, flp->f_buf, flp->f_rdsize,
  1236.             (flp->f_flags & F_READOK));
  1237.     if (fmtp == flofmt || (fmtp == decfmt &&
  1238.         (val_t) ceil((double) flp->f_curval) != flp->f_curval))
  1239.         return (R_FLOAT);
  1240.     return (fmtp? R_OK: R_NOPRINT);
  1241. }
  1242.  
  1243. /*
  1244.  * Return field number. Set 'prev' and 'addr' flags, advance formula pointer.
  1245.  */
  1246. fn(baseflp, flp, p, prev, addr, max, errok)
  1247.     register fld_t    *baseflp, *flp;
  1248.     register char    **p;
  1249.     int        *prev, *addr;
  1250. {
  1251.     register int    id, plus;
  1252.  
  1253.     if (((*addr = (**p == H_ADDR)) == 0) &&
  1254.         ((*prev = (**p == H_PREVAL)) == 0) && **p != H_CURVAL) {
  1255.         if (errok)
  1256.             return (0);
  1257.         badf(flp->f_form, *p, "not a field identifier");
  1258.     }
  1259.     (*p)++;
  1260.     if (**p == H_CURFIELD) {
  1261.         (*p)++;
  1262.         return ((flp - baseflp) + 1);
  1263.     }
  1264.     plus = (**p == '+');
  1265.     if ((id = stoi(p, "field number", 1, 1)) < 0 || (plus && id > 0))
  1266.         id = (int) (flp - baseflp) + 1 + id;
  1267.     if (id <= 0 || id > max) {
  1268.         char *pp;
  1269.         sprintf(pp = alloc((id / 10) + 2), "%d", id);
  1270.         badf(flp->f_form, pp, "invalid field number");
  1271.     }
  1272.     return (id);
  1273. }
  1274.  
  1275. /*
  1276.  * Convert a string into a positive or negative int. Handles hex and octal.
  1277.  * Advance pointer.
  1278.  */
  1279. stoi(p, what, negok, errok)
  1280.     char        *what;
  1281.     register char    **p;
  1282. {
  1283.     int        n, newval, neg, base;
  1284.  
  1285.     neg = 0;
  1286.     base = 10;
  1287.     (void) skipspaces(p);
  1288.     if (**p == '+' || (negok && (neg = (**p == '-'))))
  1289.         (*p)++;
  1290.     if (! strncmp(*p, "0x", 2)) {
  1291.         base = 16;
  1292.         (*p) += 2;
  1293.     }
  1294.     else if (**p == '0') {
  1295.         base = 8;
  1296.         (*p)++;
  1297.     }
  1298.     for (newval = 0; **p; (*p)++) {
  1299.         if ((n = conv(*p, base, what, errok)) < 0)
  1300.             break;
  1301.         newval = (newval * base) + n;
  1302.     }
  1303.     (void) skipspaces(p);
  1304.     return (neg? -newval: newval);
  1305. }
  1306.  
  1307. /*
  1308.  * Convert an ascii character into a digit.
  1309.  */
  1310. conv(p, base, what, errok)
  1311.     char        *p, *what;
  1312. {
  1313.     register char    c;
  1314.  
  1315.     if (isdigit(c = *p))
  1316.         return (c - '0');
  1317.     if (isupper(c))
  1318.         c = tolower(c);
  1319.     if (base == 16 && c >= 'a' && c <= 'f')
  1320.         return (10 + c - 'a');
  1321.     if (errok)
  1322.         return (-1);
  1323.     fprintf(stderr, "%s: illegal %s (%s)\n", pname, what, p);
  1324.     usage();
  1325.     /* NOTREACHED */
  1326. }
  1327.  
  1328. /*
  1329.  * Advance pointer to next non-space character. Return 1 pointer changed.
  1330.  */
  1331. skipspaces(p)
  1332.     register char    **p;
  1333. {
  1334.     if (! isspace(**p))
  1335.         return (0);
  1336.     while (isspace(**p))
  1337.         (*p)++;
  1338.     return (1);
  1339. }
  1340.  
  1341. /*
  1342.  * Remove trailing spaces from string.
  1343.  */
  1344. cleanspaces(str)
  1345.     register char    *str;
  1346. {
  1347.     if (str == NULL || *str == '\0')
  1348.         return;
  1349.     while (*str)
  1350.         str++;
  1351.     --str;
  1352.     while (isspace(*str))
  1353.         *str-- = '\0';
  1354. }
  1355.  
  1356. /*
  1357.  * Replace unprintable characters in a buffer by dots ('.').
  1358.  */
  1359. char *
  1360. cleanbuf(p, n)
  1361.     register char    *p;
  1362. {
  1363.     register char    *pp;
  1364.  
  1365.     for (pp = p; --n >= 0; pp++)
  1366.         if (! isprint(*pp))
  1367.             *pp = '.';
  1368.     return (p);
  1369. }
  1370.  
  1371. /*
  1372.  * Handle a format string. Return a format pointer and the width in 'width'.
  1373.  * Advance pointer.
  1374.  */
  1375. char *
  1376. prfmt(p, w, prtime, errok, str)
  1377.     char    **p;
  1378.     char    *str;
  1379.     int    *w, *prtime;
  1380. {
  1381.     *prtime = 0;
  1382.     if ((*w = stoi(p, "print width", 0, 1)) == 0)
  1383.         *w = DEF_WIDTH;
  1384.     switch (**p) {
  1385.     case 'd':
  1386.         return (decfmt);
  1387.     case 'f':
  1388.         return (flofmt);
  1389.     case 'o':
  1390.         return (octfmt);
  1391.     case 't':
  1392.         *prtime = 1;
  1393.         /* fall thru */
  1394.     case 's':
  1395.         return (strfmt);
  1396.     case 'u':
  1397.         return (unsfmt);
  1398.     case 'x':
  1399.         return (hexfmt);
  1400.     }
  1401.     if (! isalpha(**p) && errok) {
  1402.         (*p)++;
  1403.         return (DEF_FMT);
  1404.     }
  1405.     fprintf(stderr, "%s: invalid print format in '%s' (%c)\n", pname,
  1406.         str, **p);
  1407.     outputline();
  1408.     exit (1);
  1409.     /* NOTREACHED */
  1410. }
  1411.  
  1412. /*
  1413.  * Push argument onto calculator stack.
  1414.  */
  1415. push(n)
  1416.     register val_t    n;
  1417. {
  1418.     register int    i;
  1419.  
  1420.     if (cdepth++ == CDEPTH)
  1421.         return (R_ERR);
  1422.     for (i = cdepth; --i >= 0; )
  1423.         calc[i] = i? calc[i - 1]: n;
  1424.     return (R_OK);
  1425. }
  1426.  
  1427. /*
  1428.  * Pop one argument from calculator stack.
  1429.  */
  1430. pop()
  1431. {
  1432.     register int    i;
  1433.  
  1434.     if (--cdepth <= 0)
  1435.         return (R_ERR);
  1436.     for (i = 1; i <= cdepth; i++)
  1437.         if ((calc[i - 1] = calc[i]) == 0)
  1438.             break;
  1439.     return (R_OK);
  1440. }
  1441.  
  1442. /*
  1443.  * Do 'nlist' and validate name list. Validation is very basic. Note that
  1444.  * one extra 'nlist' entry was allocated to handle the additional symbol.
  1445.  */
  1446. donlist(nl, mem, max)
  1447.     register nl_t    *nl;
  1448. {
  1449.     char        *p;
  1450.     int        nproc, size;
  1451. #ifdef    SYSV
  1452.     struct        var v;
  1453.  
  1454. #ifdef    UNDERSCORESYM
  1455.     (nl + max)->n_name = "_v";
  1456. #else
  1457.     (nl + max)->n_name = "v";
  1458. #endif
  1459.     p = (char *) &v;
  1460.     size = sizeof (v);
  1461. #else    /* SYSV */
  1462. #ifdef    V7
  1463.     strncpy((nl + max)->n_name, "_nproc", SYMLENGTH);
  1464. #else
  1465. #ifdef    UNDERSCORESYM
  1466.     (nl + max)->n_name = "_nproc";
  1467. #else
  1468.     (nl + max)->n_name = "nproc";
  1469. #endif
  1470. #endif    /* V7 */
  1471.     p = (char *) &nproc;
  1472.     size = sizeof nproc;
  1473. #endif    /* SYSV */
  1474.     if (nlist (nlistf, nl) < 0) {
  1475.         fprintf(stderr, "%s: nlist(%s) failed -- ", pname, nlistf);
  1476.         perrexit("");
  1477.     }
  1478.     if ((nl + max)->n_value == 0) {
  1479.         fprintf(stderr, "%s: symbol '%s' not found in %s\n", pname,
  1480.             (nl + max)->n_name, nlistf);
  1481.         exit (1);
  1482.     }
  1483.     (void) doread((nl + max)->n_name, kmemf, mem,
  1484.         (off_t) (nl + max)->n_value, p, size, 1);
  1485. #ifdef    SYSV
  1486.     nproc = v.v_proc;
  1487. #endif
  1488.     if (nproc > 4096 || nproc < 3) {
  1489.         fprintf(stderr, "Namelist out of date\n");
  1490.         exit (1);
  1491.     }
  1492. #ifdef    NLISTBUG
  1493.     fixnlist(nl, max);
  1494. #endif
  1495. }
  1496.  
  1497. #ifdef    NLISTBUG
  1498. /*
  1499.  * If a symbol is more than once in the list, all but the first one will have
  1500.  * an n_value of zero. This normally doesn't matter, but 'nlist' can ask for
  1501.  * symbol+4 and symbol+8, for example, in which case the second one fails.
  1502.  * This is a bug present in all the nlist(3) I have tried.
  1503.  */
  1504. fixnlist(nl, max)
  1505.     register nl_t    *nl;
  1506.     register int    max;
  1507. {
  1508.     register nl_t    *np, *npp;
  1509.  
  1510.     for (np = nl; np < nl + (max - 1) ; np++)
  1511.         for (npp = np + 1; npp < nl + max; npp++)
  1512.             if (! strcmp(npp->n_name, np->n_name)) {
  1513.                 npp->n_value = np->n_value;
  1514.                 break;
  1515.             }
  1516. }
  1517. #endif    /* NLISTBUG */
  1518.  
  1519. /*
  1520.  * Generic read routine. If read size is  1, 2, 4 bytes, return that value,
  1521.  * else return 0. If okdiff is 0, don't allow read sizes != 1, 2, 4.
  1522.  */
  1523. doread(what, from, mem, offset, into, size, okdiff)
  1524.     char    *what, *from, *into;
  1525.     off_t    offset;
  1526. {
  1527.     if (debug)
  1528.         showread(what, from, offset, size, -1);
  1529.     (void) lseek(mem, offset, 0);
  1530.     if (read(mem, into, (unsigned) size) != size) {
  1531.         showread(what, from, offset, size, errno);
  1532.         if (strict) {
  1533.             outputline();
  1534.             exit (1);
  1535.         }
  1536.     }
  1537.     switch (size) {
  1538.     case sizeof (char):
  1539.         return ((int) *into);
  1540.     case sizeof (short):
  1541.         return ((int) *(short *) into);
  1542.     case sizeof (int):
  1543.         return ((int) *(int *) into);
  1544.     default:
  1545.         if (okdiff)
  1546.             return (0);
  1547.         outputline();
  1548.         fprintf(stderr, "%s: Invalid read size: %d\n", pname, size);
  1549.         exit (1);
  1550.     }
  1551.     /* NOTREACHED */
  1552. }
  1553.  
  1554. /*
  1555.  * Debug and error routine. Show read arguments.
  1556.  */
  1557. showread(what, from, offset, size, err)
  1558.     char    *what, *from;
  1559.     off_t    offset;
  1560. {
  1561.     fprintf(stderr, "%s: read ", pname);
  1562.     if (what)
  1563.         fprintf(stderr, "'%s', ", what);
  1564.     fprintf(stderr, "%d bytes @ offset 0x%x in %s", size, offset, from);
  1565.     if (err >= 0)
  1566.         fprintf(stderr, " -- %s", sys_errlist[err]);
  1567.     fprintf(stderr, "\n");
  1568. }
  1569.  
  1570. /*
  1571.  * Debug routine. Show the whole control structure.
  1572.  */
  1573. showfl(flp, n, str)
  1574.     register fld_t    *flp;
  1575.     char        *str;
  1576. {
  1577.     fprintf(stderr, "  %s: fld %d, nl %x, buf '%s', name '%s', addr %x\n",
  1578.         str, n, flp->f_nl, flp->f_buf, flp->f_nl->n_name,
  1579.         flp->f_nl->n_value);
  1580.     fprintf(stderr, "  arg '%s', form '%s', post '%s', fmt '%s'\n",
  1581.         flp->f_arg, flp->f_form, flp->f_post, flp->f_fmt);
  1582.     fprintf(stderr, "  f 0x%x, w %d, rd %d, o %d, i %d, cur %d, pre %d\n",
  1583.         flp->f_flags, flp->f_width, flp->f_rdsize, flp->f_offset,
  1584.         flp->f_incr, (long) flp->f_curval, (long) flp->f_preval);
  1585. }
  1586.  
  1587. /*
  1588.  * Allocate 'n' bytes on the heap.
  1589.  */
  1590. char *
  1591. alloc(n)
  1592. {
  1593.     char    *a;
  1594.  
  1595.     if ((a = calloc((unsigned) n, (unsigned) 1)) == 0)
  1596.         perrexit("calloc");
  1597.     return (a);
  1598. }
  1599.  
  1600. /*
  1601.  * Build an array of spaces, return the address.
  1602.  */
  1603. char *
  1604. spaces(n)
  1605. {
  1606.     static char    *sp;
  1607.     register char    *p;
  1608.  
  1609.     if (sp == NULL) {
  1610.         sp = alloc(n + 1);
  1611.         for (p = sp; --n >= 0; p++)
  1612.             *p = ' ';
  1613.     }
  1614.     return (sp);
  1615. }
  1616.  
  1617. badf(form, msg1, msg2)
  1618.     char    *form, *msg1, *msg2;
  1619. {
  1620.     outputline();
  1621.     fprintf(stderr, "%s: invalid formula '%s'", pname, form);
  1622.     if (msg1 && *msg1)
  1623.         fprintf(stderr, " (%s)", msg1);
  1624.     if (msg2 && *msg2)
  1625.         fprintf(stderr, " -- %s", msg2);
  1626.     fprintf(stderr, "\n");
  1627.     exit (1);
  1628. }
  1629.  
  1630. perrexit(str)
  1631.     char    *str;
  1632. {
  1633.     perror(str);
  1634.     exit (1);
  1635. }
  1636.  
  1637. /*ARGSUSED*/
  1638. onfpe(n)
  1639.     int    n;
  1640. {
  1641.     outputline();
  1642.     fprintf(stderr, "%s: Floating poing exception\n", pname);
  1643.     exit (1);
  1644. }
  1645.  
  1646. usage()
  1647. {
  1648.     fprintf(stderr, "Usage: %s [-aptux] [-f format] [-h header] [-l loops] [-m mem]\n\t[-n namelist] [-s sleep] [-D debug] symbol|formula...\n", pname);
  1649.     exit (1);
  1650. }
  1651. SHAR_EOF
  1652. fi
  1653. if test -f 'Makefile'
  1654. then
  1655.     echo shar: "will not over-write existing file 'Makefile'"
  1656. else
  1657. cat << \SHAR_EOF > 'Makefile'
  1658. # Makefile for nlist
  1659.  
  1660. all: nlist man
  1661.  
  1662. nlist: nlist.o
  1663.     $(CC) $(LDFLAGS) -o $@ $@.o -lm
  1664.  
  1665. clean:
  1666.     rm -f core *.o
  1667.  
  1668. clobber: clean
  1669.     rm -f nlist
  1670.  
  1671. man:
  1672.     tbl < nlist.8 | nroff -man > nlist.man
  1673. SHAR_EOF
  1674. fi
  1675. if test -f 'chars.sun'
  1676. then
  1677.     echo shar: "will not over-write existing file 'chars.sun'"
  1678. else
  1679. cat << \SHAR_EOF > 'chars.sun'
  1680. #! /bin/sh
  1681.  
  1682. echo "Showing character I/O statistics"
  1683.  
  1684. nlist -t -s 2 -f9d \
  1685.     '_tk_nin    :    "Chars in"' \
  1686.     '_tk_nout    :    "Chars out"' \
  1687.     '#. = #1 #2 +    :     Total' \
  1688.     '#1 100 * #3 /    :    "% Input"'  \
  1689.     '#2 100 * #3 /    :    "% Output"' 
  1690. SHAR_EOF
  1691. fi
  1692. if test -f 'config.sh'
  1693. then
  1694.     echo shar: "will not over-write existing file 'config.sh'"
  1695. else
  1696. cat << \SHAR_EOF > 'config.sh'
  1697. #! /bin/sh
  1698.  
  1699. echo "Checking configuration and building 'nlist'"
  1700.  
  1701. CFLAGS="-O"
  1702. if [ -f /unix ]; then
  1703.     echo "This looks like a System 5 system"
  1704.     CFLAGS="${CFLAGS} -DSYSV"
  1705.     NAMELIST=/unix
  1706.     getmain() grep -c '_main[     ]'
  1707. elif [ -f /vmunix ]; then
  1708.     echo "This looks like a BSD system"
  1709.     NAMELIST=/vmunix
  1710.     getmain() grep -c '_main$'
  1711. else
  1712.     echo "No /unix and no /vmunix. What system are you?" >&2
  1713.     exit 1
  1714. fi
  1715.  
  1716. if [ `nm ${NAMELIST} | getmain` -gt 0 ]; then
  1717.     CFLAGS="${CFLAGS} -DUNDERSCORESYM"
  1718.     MSG=prepends
  1719. else
  1720.     MSG="doesn't prepend"
  1721. fi
  1722.  
  1723. echo "It looks like the loader ${MSG} an underscore to symbol names"
  1724. echo "If this is not right, 'nlist' may fail. Build it manually"
  1725.  
  1726. echo ""
  1727. echo "Making 'nlist'"
  1728.  
  1729. make nlist CFLAGS="${CFLAGS}"
  1730. SHAR_EOF
  1731. fi
  1732. if test -f 'dnlc.sun'
  1733. then
  1734.     echo shar: "will not over-write existing file 'dnlc.sun'"
  1735. else
  1736. cat << \SHAR_EOF > 'dnlc.sun'
  1737. #! /bin/sh
  1738.  
  1739. echo "Dumping 100 entries of the dnlc (ncache) structures,
  1740. following the 'hash_next' pointer"
  1741.  
  1742. nlist -ax -h1 -s 0 -f6x -l 10 \
  1743.     '_ncache    : Hshnxt' \
  1744.     '        : Hshprv' \
  1745.     '        : Lrunxt' \
  1746.     '        : Lruprv' \
  1747.     '        : Vp' \
  1748.     '        : Dp' \
  1749.     '|1        : Len%3d' \
  1750.     '|15        : Name%15s' \
  1751.     '        : Ucred' \
  1752.     '@&1 = #1'
  1753. SHAR_EOF
  1754. fi
  1755. if test -f 'file.sun'
  1756. then
  1757.     echo shar: "will not over-write existing file 'file.sun'"
  1758. else
  1759. cat << \SHAR_EOF > 'file.sun'
  1760. #! /bin/sh
  1761.  
  1762. echo "Dumping 10 entries of the file table. Note that _file is the ADDRESS of
  1763. the file table and not the file table itself"
  1764.  
  1765. # description (lines following the 'nlist' line)
  1766. # line 1:     header
  1767. # line 2:     read '_file' once
  1768. # line 3:     set address of next field to content of previous field
  1769. # line 4:     read that and increment by 26 next time
  1770. # line 5:     read rest of structure with auto increment
  1771.  
  1772. nlist -a -s 0 -f7x -h 1 -l 10           \
  1773.     '^. 1 +        :"  #"     %3d' \
  1774.     '_file!'                        \
  1775.     '&+1!#-1'                       \
  1776.     '>26        : flag     %4o' \
  1777.     '|2        : type     %6x' \
  1778.     '|2        : count    %6d' \
  1779.     '|2        : msgcount %6d' \
  1780.     '        : fops'         \
  1781.     '        : fdata'        \
  1782.     '        : offset   %6x' \
  1783.     '        : cred'         \
  1784.     '&. = #-1 |2    : Crref    %5d' \
  1785.         '|2        : Uid      %4u' \
  1786.         '|2        : Gid      %4u'
  1787.  
  1788. SHAR_EOF
  1789. fi
  1790. if test -f 'file.sys53'
  1791. then
  1792.     echo shar: "will not over-write existing file 'file.sys53'"
  1793. else
  1794. cat << \SHAR_EOF > 'file.sys53'
  1795. #! /bin/sh
  1796.  
  1797. echo "Dumping 50 entries of the file table"
  1798.  
  1799. nlist -ap -s 0 -fd -h 2 -l 50 \
  1800.     '^. 1 +:  #%3d' \
  1801.     '_file>12|1:Flag%4o' \
  1802.     '&.=&-1 2+|2:Count%5u' \
  1803.     ':"Inode"%10x' \
  1804.     ':"Offset"%10d'
  1805. SHAR_EOF
  1806. fi
  1807. if test -f 'minfo.sys5'
  1808. then
  1809.     echo shar: "will not over-write existing file 'minfo.sys5'"
  1810. else
  1811. cat << \SHAR_EOF > 'minfo.sys5'
  1812. #! /bin/sh
  1813.  
  1814. echo "Dumping the 'minfo' structure. Unique lines only, every 2 seconds"
  1815.  
  1816. nlist -atu -f8d -s 2            \
  1817.     'minfo        : FreeM %5d'    \
  1818.     '        : FreeS %5d'    \
  1819.     '        : Vflt'        \
  1820.     '        : Demd'        \
  1821.     '        : Swap  %5d'    \
  1822.     '        : Cache'    \
  1823.     '        : File'        \
  1824.     '        : Pfault'    \
  1825.     '        : CopyWr'    \
  1826.     '        : Steal'    \
  1827.     '        : Freed'    \
  1828.     '        : UmodS'    \
  1829.     '        : UmodF'
  1830. SHAR_EOF
  1831. fi
  1832. if test -f 'mount.sun'
  1833. then
  1834.     echo shar: "will not over-write existing file 'mount.sun'"
  1835. else
  1836. cat << \SHAR_EOF > 'mount.sun'
  1837. #! /bin/sh
  1838.  
  1839.     echo "Dumping 10 entries of the mount table"
  1840.  
  1841.  
  1842.     nlist -p -aa -s 0 -f 10x -l 10        \
  1843.         '^. 1 +    : " #"%2d'        \
  1844.         '_mounttab>28    : Vfsp'        \
  1845.         '  |1        : Maj      %3o'    \
  1846.         '  |1        : Min      %3o'    \
  1847.         '        : Devvp'    \
  1848.         '        : Bufp'        \
  1849.         '        : Qinod'    \
  1850.         '        : Qflags  |2'    \
  1851.         '        : Btime   %6d'    \
  1852.         '        : Ftime   %6d'
  1853. SHAR_EOF
  1854. fi
  1855. if test -f 'mount.sys53'
  1856. then
  1857.     echo shar: "will not over-write existing file 'mount.sys53'"
  1858. else
  1859. cat << \SHAR_EOF > 'mount.sys53'
  1860.  
  1861. SHAR_EOF
  1862. fi
  1863. if test -f 'syserr.sys5'
  1864. then
  1865.     echo shar: "will not over-write existing file 'syserr.sys5'"
  1866. else
  1867. cat << \SHAR_EOF > 'syserr.sys5'
  1868. #! /bin/sh
  1869.  
  1870. echo "Dumping the 'syserr' structure. Unique lines only, every 2 seconds"
  1871.  
  1872. nlist -atu -f7d -s 2 \
  1873.     'syserr        :InoOvf' \
  1874.     '        :FileOvf' \
  1875.     '        :TextOvf' \
  1876.     '        :ProcOvf' \
  1877.     '        :Silo' \
  1878.     '        :CrdRds' \
  1879.     '        :Alerts' \
  1880.     '        :Faults' \
  1881.     '        :Timeouts'
  1882. SHAR_EOF
  1883. fi
  1884. if test -f 'sysinfo1.sys5'
  1885. then
  1886.     echo shar: "will not over-write existing file 'sysinfo1.sys5'"
  1887. else
  1888. cat << \SHAR_EOF > 'sysinfo1.sys5'
  1889. #! /bin/sh
  1890.  
  1891. echo "Dumping part of the 'sysinfo' structure. Unique lines only, every 2 seconds"
  1892.  
  1893. nlist -atu -f8d -s 2 \
  1894.     'sysinfo    :CPU_IDLE' \
  1895.     '        :CPU_USER' \
  1896.     '        :CPU_KERN' \
  1897.     '        :CPU_WAIT' \
  1898.     '        :WAIT_IO' \
  1899.     '        :WAIT_SWP' \
  1900.     '        :WAIT_PIO'
  1901. SHAR_EOF
  1902. fi
  1903. if test -f 'sysinfo2.sys5'
  1904. then
  1905.     echo shar: "will not over-write existing file 'sysinfo2.sys5'"
  1906. else
  1907. cat << \SHAR_EOF > 'sysinfo2.sys5'
  1908. #! /bin/sh
  1909.  
  1910. echo "Dumping part of the 'sysinfo' structure. Unique lines only, every 2 seconds"
  1911.  
  1912. nlist -atu -f8d -s 2 \
  1913.     'sysinfo+28    :Breads' \
  1914.     '        :Bwrites' \
  1915.     '        :Lreads' \
  1916.     '        :Lwrites' \
  1917.     '        :Phreads' \
  1918.     '        :Phwrites' \
  1919.     '        :Swapin' \
  1920.     '        :Swapout' \
  1921.     '        :Bswapin' \
  1922.     '        :Bswapout'
  1923. SHAR_EOF
  1924. fi
  1925. if test -f 'sysinfo3.sys5'
  1926. then
  1927.     echo shar: "will not over-write existing file 'sysinfo3.sys5'"
  1928. else
  1929. cat << \SHAR_EOF > 'sysinfo3.sys5'
  1930. #! /bin/sh
  1931.  
  1932. echo "Dumping part of the 'sysinfo' structure. Unique lines only, every 2 seconds"
  1933.  
  1934. nlist -atu -f8d -s 2 \
  1935.     'sysinfo+68    :PSwtches' \
  1936.     '        :Syscall' \
  1937.     '        :SReads' \
  1938.     '        :SWrites' \
  1939.     '        :SForks %6d' \
  1940.     '        :SExecs %6d' \
  1941.     '        :RunQ' \
  1942.     '        :RunOcc' \
  1943.     '        :SwpQ %5d' \
  1944.     '        :SwpOcc %5d'
  1945. SHAR_EOF
  1946. fi
  1947. if test -f 'sysinfo4.sys5'
  1948. then
  1949.     echo shar: "will not over-write existing file 'sysinfo4.sys5'"
  1950. else
  1951. cat << \SHAR_EOF > 'sysinfo4.sys5'
  1952. #! /bin/sh
  1953.  
  1954. echo "Dumping part of the 'sysinfo' structure. Unique lines only, every 2 seconds"
  1955.  
  1956. nlist -atu -f9d -s 2 \
  1957.     'sysinfo+108        :Iget' \
  1958.     '            :Namei' \
  1959.     '            :Dirblks' \
  1960.     '            :Readch' \
  1961.     '            :Writech' \
  1962.     '#-2 100 * #-1 #-2 + /    : "% Reads"
  1963. SHAR_EOF
  1964. fi
  1965. if test -f 'sysinfo5.sys5'
  1966. then
  1967.     echo shar: "will not over-write existing file 'sysinfo5.sys5'"
  1968. else
  1969. cat << \SHAR_EOF > 'sysinfo5.sys5'
  1970. #! /bin/sh
  1971.  
  1972. echo "Dumping part of the 'sysinfo' structure. Unique lines only, every 2 seconds"
  1973.  
  1974. nlist -atu -f8d -s 2 \
  1975.     'sysinfo+128    :RcvInts' \
  1976.     '        :XmtInts' \
  1977.     '        :MdmInts' \
  1978.     '        :RawCh' \
  1979.     '        :CanCh' \
  1980.     '        :OutCh' \
  1981.     '        :Msg %4d' \
  1982.     '        :Sema %4d'
  1983. SHAR_EOF
  1984. fi
  1985. if test -f 'sar-s'
  1986. then
  1987.     echo shar: "will not over-write existing file 'sar-s'"
  1988. else
  1989. cat << \SHAR_EOF > 'sar-s'
  1990. #! /bin/sh
  1991.  
  1992. LOOPS=${1:-100}
  1993. echo "This will do what 'sar -s 1 1 ${LOOPS}' does"
  1994.  
  1995. echo "`uname -a`    `date +%D`\n"
  1996.  
  1997. nlist -xat -f7u -s 1 -h1 -l ${LOOPS}        \
  1998.     '@sysinfo'                \
  1999.     '@'                    \
  2000.     '@'                    \
  2001.     '@'                    \
  2002.     '@#1 ^1 -'                \
  2003.     '@#2 ^2 -'                \
  2004.     '@#3 ^3 -'                \
  2005.     '@#4 ^4 -'                \
  2006.     '@#-1 #-2 #-3 #-4 +++'            \
  2007.     '#6 100 * #-1 /: "%usr"'        \
  2008.     '#7 100 * #-2 /: "%sys"'        \
  2009.     '#8 100 * #-3 /: "%wio"'        \
  2010.     '#5 100 * #-4 /: "%idle"'        | \
  2011.     awk 'BEGIN {l=0; u=0; s=0; w=0; i=0}    \
  2012.            {printf "%8s %7s %7s %7s %7s\n", $1, $2, $3, $4, $5} \
  2013.            $2 != "%usr" {l += 1; u += $2; s += $3; w += $4; i += $5} \
  2014.          END   {printf "\nAverage  %7d %7d %7d %7d\n", u/l, s/l, w/l, i/l}'
  2015.  
  2016. SHAR_EOF
  2017. fi
  2018. exit 0
  2019. #    End of shell archive
  2020. ---------------------------------- cut here -------------------------------
  2021. -- 
  2022. Chris Bertin    | -- CETIA -- 150, Av Marcelin Berthelot, Z.I. Toulon-Est
  2023. +33(94)212005    | 83088 Toulon Cedex, France
  2024.         | inria!cetia!chris
  2025.  
  2026.  
  2027.